/**
 * 缓存
 * 1、babel  缓存。js代码一定是最多的。
 */
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 压缩css
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

/**
 * 缓存：
 * 	babel 缓存。直接配置：“cacheDirectory” 为 true。
 * 	让第二次打包构建速度更快。
 *
 * 文件资源缓存：
 * 	hash。每次构建会生成一个唯一的hash值。
 * 		问题：因为js和css同时使用一个hash值。
 * 		如果从新打包，会导致所有缓存失效。可能只改动一个文件。
 *  chunkhash：根据chunk生成的hash值。如果打包来源于同一个chunk，hash值就一样。
 * 		问题：js和css的hash值是一样的。
 * 		原因：因为css是js中被引入，同属于一个chunk（代码块），同属于一个入口文件。
 * 	contenthash：根据文件的内容生成hash，所有的hash值都不同。
 * 	让代码上线运行缓存更好使用。
 *
 */
module.exports = {
  entry: [
    resolve(__dirname, './src/js/index.js'),
    resolve(__dirname, './src/index.html'),
  ],
  output: {
    // 这里是为了替换express服务器中的缓存
    // filename: 'js/built.[hash:10].js',
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      // 这样做是为了让所有的js都过这个eslint检查
      // 下面的oneOf，只会过一个loader
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        // 优先执行
        enforce: 'pre',
        options: {
          // 自动修复eslint的错误
          fix: true,
        },
      },
      {
        // 这样保证不是每个loader都会被过一次
        // 否则每个都会过一次浪费性能。
        oneOf: [
          // 处理样式资源
          {
            test: /\.less$/,
            // 使用多个loader处理用use
            use: ['style-loader', 'css-loader', 'less-loader'],
          },
          {
            test: /\.css$/,
            // 使用多个loader处理用use
            use: [MiniCssExtractPlugin.loader, 'css-loader'],
          },
          // 处理样式中的图片资源
          // 无法在html中通过src引用图片，只能在css中引入。
          {
            test: /\.(jpg|png|gif)$/,
            // 处理样式文件中的图片url的路径问题的。
            // 需要下载 url-loader 和 file-loader
            loader: 'url-loader',
            options: {
              // 图片小于8kb，就会被base64处理。也就是写入css中。
              // 有点：减少请求数量，减轻服务器压力。
              // 缺点：图片体积会更大，文件请求速度更慢。
              limit: 8 * 1024,
              // html-loader使用commonjs去解析，而url-loader使用es6解析，所以这里需要这样设置。
              esModule: false,
              // name: '[hash:10].[ext]',
              name: '[contenthash:10].[ext]',
              outputPath: 'imgs',
            },
          },
          {
            test: /\.html$/,
            // 处理html文件的img图片，负责引入图片，然后能被url-loader处理。
            loader: 'html-loader',
          },
          {
            /**
             * 缓存，如果只有一个js文件修改，其他的99个修改就别翻译了。
             *
             */
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              // 预设：指示babel做兼容性处理
              // 也就是转化为es5，可是这个方法不行啊。
              // 这是基本的js兼容处理，无法处理promise
              presets: [
                [
                  // 基本的兼容
                  '@babel/preset-env',
                  // 按需兼容
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3 },
                    // 指定兼容性做到哪个版本的浏览器
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '11',
                      safari: '10',
                      edge: '17',
                    },
                  },
                ],
              ],
              // 开启缓存，第二次构建之前，浏览器会读取第一次的缓存.
              cacheDirectory: true,
            },
          },
          {
            exclude: /\.(html|js|css|less|jpg|png|gif)$/,
            loader: 'file-loader',
            options: {
              // name: '[hash:10].[ext]',
              name: '[contenthash:10].[ext]',
              outputPath: 'media',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: resolve(__dirname, './src/index.html'),
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
    new MiniCssExtractPlugin({
      // 重命名输出的文件
      // filename: 'css/built.[hash:10].css',
      // 这里使用内容hash，名字不会重复了。
      filename: 'css/built.[contenthash:10].css',
    }),
    // 压缩css
    new OptimizeCssAssetsPlugin(),
  ],
  /**
   * 开发服务器，用来自动编译，自动打开浏览器，自动刷新浏览器
   * 特点：只会在内存中编译打包，不会有任何 输出
   * 启动devServer指令：npx webpack-dev-server
   */
  devServer: {
    contentBase: [resolve(__dirname, 'build')],
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 3000,
    open: true,
    // 开启HMR功能
    hot: true,
  },
  // 这里一定要加这个，否则不会热更新的。
  target: 'web',
  mode: 'development',
  devtool: 'eval-source-map',
}
